﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;
using System.Configuration;

namespace BoardAppUtil.Security
{
    /// <summary>
    ///  <title></title>
    ///  <description></description>
    ///  <copyRight>Copyright (c) 2012</copyRight>
    ///  <company>IronOne Technologies (Pvt)Ltd</company>
    ///  <createdOn>2012-</createdOn>
    ///  <author></author>
    ///  <modification>
    ///     <modifiedBy></modifiedBy>
    ///      <modifiedDate></modifiedDate>
    ///     <description></description>
    ///  </modification>
    /// </summary>
   public class CryptoServices
    {

        #region Member Variables
        #endregion


        #region Properties
        #endregion

        #region Constructors

        /// <summary>
        ///  <description>The default Constructor.</description>
        ///  <param></param>
        ///  <returns>
        ///  </returns>       
        ///  <exception>
        ///  </exception>
        ///  <remarks></remarks>
        /// </summary>
      
        #endregion

        #region Functions

        #region PublicFunctions

       public static String EncryptFile(string inputFile, string fileName, string closefilepath)
        {
            //EventLog.Info(String.Format(Resources.log_evt_entry_EncryptFile, EventStatus.Entry.ToString(), inputFile, fileName));

            string outputFile = ConfigurationManager.AppSettings["DFP"].ToString() + "\\" + DateTime.Now.ToString().Replace("/", "_").Replace(" ", "_").Replace(":", "_") + fileName;

            if (System.IO.File.Exists(inputFile)) //check is file is there
            {
                try
                {

                    #region oldencryption
                    //const string password = @"myKey123"; // Your Key Here
                    //UnicodeEncoding UE = new UnicodeEncoding();
                    //byte[] key = UE.GetBytes(password);

                    //string cryptFile = outputFile;
                    //FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create);
                    //CryptoStream cs;

                    ////if ("AES".Equals(BoardAppUtil.Settings.Settings.GetEncryptionType(), StringComparison.OrdinalIgnoreCase))
                    ////{
                    ////    AesManaged AesCrypto = new AesManaged();
                    ////    AesCrypto.KeySize = 256;
                    ////    cs = new CryptoStream(fsCrypt, AesCrypto.CreateEncryptor(key, key), CryptoStreamMode.Write);
                    ////}
                    ////else
                    ////{
                    //RijndaelManaged RMCrypto = new RijndaelManaged();
                    //cs = new CryptoStream(fsCrypt, RMCrypto.CreateEncryptor(key, key), CryptoStreamMode.Write);
                    ////}

                    ////AesCryptoServiceProvider AesCryptoProvider = new AesCryptoServiceProvider();
                    ////cs = new CryptoStream(fsCrypt, AesCryptoProvider.CreateEncryptor(key, AesCryptoProvider.IV), CryptoStreamMode.Write);

                    //FileStream fsIn = new FileStream(inputFile, FileMode.Open);

                    //int data;
                    //while ((data = fsIn.ReadByte()) != -1)
                    //    cs.WriteByte((byte)data);

                    //fsIn.Close();
                    //cs.Close();
                    //fsCrypt.Close();
                    //System.IO.File.Delete(inputFile);
                    #endregion


                    //Set up the encryption objects
                    using (AesCryptoServiceProvider acsp = GetProvider(Encoding.Default.GetBytes(closefilepath)))
                    {
                        ICryptoTransform ictE = acsp.CreateEncryptor();

                        FileStream filetoEncrypt = new FileStream(outputFile, FileMode.Create);

                        //Perform the encrpytion, storing output into the stream
                        CryptoStream csS = new CryptoStream(filetoEncrypt, ictE, CryptoStreamMode.Write);

                        FileStream fsIn = new FileStream(inputFile, FileMode.Open);

                        int data;
                        while ((data = fsIn.ReadByte()) != -1)
                            csS.WriteByte((byte)data);

                        fsIn.Close();
                        csS.Close();
                        filetoEncrypt.Close();
                    }

                }
                catch (Exception e)
                {
                    // Cannot encrypt PDF file at this moment. 326
                   // EventLog.Info(String.Format(Resources.log_err_326_EncryptFile, EventStatus.Failure.ToString()) + Resources.err_326);
                }
                finally
                {
                    System.IO.File.Delete(inputFile);
                }
            }
            else
            {
                //If there is no such file 
               // EventLog.Info(String.Format(Resources.log_err_329_EncryptFile, EventStatus.Failure.ToString()) + Resources.err_329_sys);
            }
            return outputFile;
        }

        public static string DecryptFile(string inputFile, string fileName, string openfilepath)
        {
            //EventLog.Info(String.Format(Resources.log_evt_entry_DecryptFile, EventStatus.Entry.ToString(), User.Identity.Name, inputFile));
            //Logs.WriteLogToDb(String.Format(Resources.log_evt_entry_DecryptFile, EventStatus.Entry.ToString(), User.Identity.Name, inputFile));
            string outputFile = String.Empty;
            try
            {
                if (String.IsNullOrEmpty(fileName))
                {
                    Random r = new Random();
                    outputFile = ConfigurationManager.AppSettings["DFP"] + "\\" +
                                 DateTime.Now.ToString().Replace("/", "_").Replace(" ", "_").Replace(":", "_") + "_" + r.Next() + ".pdf";
                }
                else
                {
                    outputFile = ConfigurationManager.AppSettings["DFP"] + "\\" + fileName + ".pdf";
                    if (System.IO.File.Exists(outputFile))
                    {
                        outputFile = ConfigurationManager.AppSettings["DFP"] + "\\" + fileName + "_(1)" + ".pdf";
                    }
                }

                #region oldDecryptCode

                //const string password = @"myKey123"; // Your Key Here
                ////string password = @"0123456789012345";

                //UnicodeEncoding UE = new UnicodeEncoding();
                //byte[] key = UE.GetBytes(password);

                //FileStream fsCrypt = new FileStream(inputFile, FileMode.Open);// Here should come try catch unless IOExeption can occure
                //CryptoStream cs;

                ////if ("AES".Equals(BoardAppUtil.Settings.Settings.GetEncryptionType(), StringComparison.OrdinalIgnoreCase))
                ////{
                ////    AesManaged AesCrypto = new AesManaged();
                ////    AesCrypto.KeySize = 256;
                ////    cs = new CryptoStream(fsCrypt, AesCrypto.CreateDecryptor(key, key), CryptoStreamMode.Read);
                ////}
                ////else
                ////{
                //RijndaelManaged RMCrypto = new RijndaelManaged();
                //cs = new CryptoStream(fsCrypt, RMCrypto.CreateDecryptor(key, key), CryptoStreamMode.Read);
                ////}

                ////AesCryptoServiceProvider AesCryptoProvider = new AesCryptoServiceProvider();
                ////cs = new CryptoStream(fsCrypt, AesCryptoProvider.CreateDecryptor(key, AesCryptoProvider.IV), CryptoStreamMode.Read);

                //FileStream fsOut = new FileStream(outputFile, FileMode.Create);

                //int data;
                //while ((data = cs.ReadByte()) != -1)
                //    fsOut.WriteByte((byte)data);

                //fsOut.Close();
                //cs.Close();
                //fsCrypt.Close();

                #endregion

                using (AesCryptoServiceProvider acsp = GetProvider(Encoding.Default.GetBytes(openfilepath)))
                {
                    ICryptoTransform ictD = acsp.CreateDecryptor();

                    FileStream fsIn = new FileStream(inputFile, FileMode.Open);

                    CryptoStream csD = new CryptoStream(fsIn, ictD, CryptoStreamMode.Read);

                    FileStream fsOut = new FileStream(outputFile, FileMode.Create);

                    int data;
                    while ((data = csD.ReadByte()) != -1)
                        fsOut.WriteByte((byte)data);

                    fsOut.Close();
                    csD.Close();
                    fsIn.Close();
                }

                #region MyRegion

                //HttpContext context = System.Web.HttpContext.Current;

                //context.Response.Buffer = false;
                //context.Response.Clear();
                //context.Response.ClearContent();
                //context.Response.ClearHeaders();

                //// Set the appropriate ContentType.
                //context.Response.ContentType = "application/pdf";
                //context.Response.AddHeader("Content-Disposition", "inline; filename=Report.pdf");
                //context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
                //try
                //{
                //    // Write the file directly to the HTTP content output stream.
                //    //context.Response.WriteFile(outputFile);
                //    //context.ApplicationInstance.CompleteRequest();

                //}
                //catch (IOException)
                //{ }
                //finally
                //{
                //    System.IO.File.Delete(outputFile);
                //}
                //System.Diagnostics.Process p = System.Diagnostics.Process.Start(outputFile);
                //  p.WaitForExit();
                //  File.Delete(outputFile);
                // } 

                #endregion
            }
            catch (Exception e)
            {                
                //ErrorLog.Error("327, ERR, " + EventStatus.Failure.ToString() + ", Paper, DecryptFile, " +
                //    /* User.Identity.Name + */ ", " + e.Message + " ," + e.InnerException + ", Stack Trace: " +
                //               e.StackTrace);
            }
            return outputFile;
        }
        #endregion

        #region PrivateFunctions

        private static AesCryptoServiceProvider GetProvider(byte[] key)
        {
            AesCryptoServiceProvider result = new AesCryptoServiceProvider();
            result.BlockSize = 128;
            result.KeySize = 256;
            result.Mode = CipherMode.CBC;
            result.Padding = PaddingMode.PKCS7;

            result.GenerateIV();
            result.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

            byte[] RealKey = GetKey(key, result);
            result.Key = RealKey;
            // result.IV = RealKey;
            return result;
        }

        private static byte[] GetKey(byte[] suggestedKey, SymmetricAlgorithm p)
        {
            byte[] kRaw = suggestedKey;
            List<byte> kList = new List<byte>();

            for (int i = 0; i < p.LegalKeySizes[0].MinSize; i += 8)
            {
                kList.Add(kRaw[(i / 8) % kRaw.Length]);
            }
            byte[] k = kList.ToArray();
            return k;
        }
        #endregion

        #endregion

    }
}
